package NG::Sys::Cached::Common::Parent;
use strict;
use warnings;
use utf8;

sub new {
	my $class = shift;
	my %arg;
	if(ref $_[0]){
		%arg = %{$_[0]};
	}elsif(@_ % 2){
		die "odd number params\n";
	}else{
		%arg = @_;
	}
	unless($arg{app}){
		die "need app\n";
	}
	unless($arg{namespace}){
		die "need namespace\n";
	}
	my $orig_cache;
	unless(defined ($orig_cache = $arg{cache})){
		die "need cache\n";
	}elsif(UNIVERSAL::isa($orig_cache,"NG::Sys::Cache::Base")){
		$arg{cache} = $orig_cache->clone($arg{namespace});
	}elsif(ref $orig_cache){
		$arg{cache} = $arg{app}->get_cache(%$orig_cache);
	}elsif(!$orig_cache){
		$arg{cache} = $arg{app}->get_cache("nocache");
	}elsif($orig_cache){
		$arg{cache} = $arg{app}->get_cache($orig_cache);
	}else{
		die "bad cache specification\n";
	}

	my $self = bless \%arg, $class;

	if($self->{compress}){
		require Compress::Zlib;
	}

	$self->init;
	return $self;
}
sub init {
}
sub make_subclass {
	my ($self,$class) = @_;
	my $nc = "tmp".(0 + $self);
	eval <<"ECD";
package $nc;
our \@ISA = qw($class);
our \$VERSION = 1.0;
ECD
	return $nc;
}
sub count_action {
	my ($self,$action) = @_;
	my $context = $self->{app}->get_context("counter");
	($context->{ $self->{namespace} }{$action} ||= 0 )++;
}
sub context {
	my ($self) = @_;
	return $self->{app}->get_context(int $self);
}
sub cache {
	my ($self) = @_;
	return $self->{cache};
}
sub drop_context {
	my ($self,$id) = @_;
	my $c = $self->context;
	$self->count_action("drop");
	delete $c->{$id};
}
sub clear_cache {
	my ($self,$id) = @_;
	my $c = $self->context;
	delete $c->{$id};
	$self->count_action("clear");
	$self->{cache}->remove($id);
}

package NG::Sys::Cached::Common::Child;
use strict;
use warnings;
use utf8;

sub drop_context {
	my ($self) = @_;
	$self->{parent}->drop_context($self->{id});
}
sub clear_cache {
	my ($self) = @_;
	$self->{parent}->clear_cache($self->{id});
}
sub set_cache {
	my ($self,$key,@rest) = @_;
	return $self->{parent}{cache}->set($self->{id}.":".$key,@rest);
}
sub get_cache {
	my ($self,$key,@rest) = @_;
	return $self->{parent}{cache}->get($self->{id}.":".$key,@rest);
}
sub remove_cache {
	my ($self,$key,@rest) = @_;
	return $self->{parent}{cache}->remove($self->{id}.":".$key,@rest);
}
sub DESTROY {}
1;
